package top.gytf.unifiedcall.common.contract;

import lombok.Getter;
import lombok.Setter;
import top.gytf.distools.lifecycle.AbstractLifecycle;
import top.gytf.distools.lifecycle.Manager;
import top.gytf.unifiedcall.model.contract.ApiContract;

import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

@Setter
@Getter
public class ApiContractManagerImpl extends AbstractLifecycle implements ApiContractManager, Manager {
    private ApiContractReader apiContractReader;
    private List<ApiContractReader> apiContractReaders;
    private Map<Method, List<ApiContract>> cache = new ConcurrentHashMap<>();

    /**
     * 初始化逻辑
     */
    @Override
    public void doInitialize() {
        // 处理ApiContractReader
        postProcessApiContractReaders(apiContractReaders);
        apiContractReader = new CompositeApiContractReader(apiContractReaders);
        apiContractReader.initialize();
    }

    @Override
    protected void doDestroy() {
        apiContractReader.destroy();
        cache.clear();
    }

    @Override
    public void load(Method apiMethod) {
        assertReady();

        cache.computeIfAbsent(apiMethod, method -> {
            if (!apiContractReader.isSupported(method)) {
                return Collections.emptyList();
            }
            return apiContractReader.read(method);
        });
    }

    @Override
    public List<ApiContract> findContracts(Method apiMethod, boolean loadIfNeed) {
        assertReady();

        List<ApiContract> supportedContracts = cache.get(apiMethod);
        if (supportedContracts == null && loadIfNeed) {
            // 不存在则加载
            load(apiMethod);
            supportedContracts = cache.get(apiMethod);
        }

        return Optional.ofNullable(supportedContracts)
                .orElse(Collections.emptyList());
    }

    /**
     * 后置处理协议读取器列表
     *
     * @param apiContractReaders 入选的ApiContractReader列表
     */
    protected void postProcessApiContractReaders(@SuppressWarnings("unused") List<ApiContractReader> apiContractReaders) {
        // do nothing
    }
}
